package top.jiangqiang.crawler.core.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.date.DatePattern;
import top.jiangqiang.crawler.core.exception.CrawlerException;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

/**
 * 此类
 *
 * @author Jiangqiang
 * @version 1.0
 * @description jackson实现的json解析工具类
 * @date 2022/8/25 10:12
 */
@Slf4j
public class JsonUtil {
    public final static LocalDateTimeSerializer localDateTimeSerializer = new LocalDateTimeSerializer(DatePattern.NORM_DATETIME_FORMATTER);
    public final static LocalDateSerializer localDateSerializer = new LocalDateSerializer(DatePattern.NORM_DATE_FORMATTER);
    public final static LocalTimeSerializer localTimeSerializer = new LocalTimeSerializer(DatePattern.NORM_TIME_FORMATTER);
    public final static LocalDateTimeDeserializer localDateTimeDeserializer = new LocalDateTimeDeserializer(DatePattern.NORM_DATETIME_FORMATTER);
    public final static LocalDateDeserializer localDateDeserializer = new LocalDateDeserializer(DatePattern.NORM_DATE_FORMATTER);
    public final static LocalTimeDeserializer localTimeDeserializer = new LocalTimeDeserializer(DatePattern.NORM_TIME_FORMATTER);
    private final static ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    static {
        init();
    }

    /**
     * 初始化ObjectMapper通用配置
     */
    private static void init() {
        //忽略未知属性
        JsonUtil.OBJECT_MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        //忽略null的属性
        JsonUtil.OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        JsonUtil.OBJECT_MAPPER.registerModule(buildJavaTimeModule());
    }

    /**
     * 注册java8相关的日期时间序列化
     *
     * @return
     */
    public static JavaTimeModule buildJavaTimeModule() {
        //支持序列化和反序列化LocalDateTime类型
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, localDateTimeSerializer);
        javaTimeModule.addSerializer(LocalDate.class, localDateSerializer);
        javaTimeModule.addSerializer(LocalTime.class, localTimeSerializer);
        javaTimeModule.addDeserializer(LocalDateTime.class, localDateTimeDeserializer);
        javaTimeModule.addDeserializer(LocalDate.class, localDateDeserializer);
        javaTimeModule.addDeserializer(LocalTime.class, localTimeDeserializer);
        return javaTimeModule;
    }

    /**
     * 转为JSON字符串，格式化输出
     *
     * @param object
     * @return JSON字符串
     */
    public static String toJsonPrettyStr(Object object) {
        try {
            if (object == null) {
                return null;
            }
            return OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new CrawlerException(e);
        }
    }

    /**
     * 转为JSON字符串
     *
     * @param object
     * @return JSON字符串
     */
    public static String toJsonStr(Object object) {
        try {
            if (object == null) {
                return null;
            }
            return OBJECT_MAPPER.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new CrawlerException(e);
        }
    }

    /**
     * @param jsonStr json字符串
     * @param tClass  class
     * @param <T>     指定类型
     * @return json转对象
     */
    public static <T> T parse(String jsonStr, Class<T> tClass) {
        try {
            if (jsonStr == null) {
                return null;
            }
            return OBJECT_MAPPER.readValue(jsonStr, tClass);
        } catch (JsonProcessingException e) {
            throw new CrawlerException(e);
        }
    }

    /**
     * 集合：
     * TypeFactory.defaultInstance().constructCollectionType(collectionClass, itemClass)
     * 数组：
     * TypeFactory.defaultInstance().constructArrayType(itemClass)
     *
     * @param jsonStr  json字符串
     * @param javaType 类型
     * @param <T>
     * @return
     */
    public static <T> T parse(String jsonStr, JavaType javaType) {
        try {
            if (jsonStr == null) {
                return null;
            }
            return OBJECT_MAPPER.readValue(jsonStr, javaType);
        } catch (JsonProcessingException e) {
            throw new CrawlerException(e);
        }
    }

    /**
     * 反序列化嵌套的泛型
     *
     * @param jsonStr      json字符串
     * @param valueTypeRef 类型
     * @param <T>
     * @return
     */
    public static <T> T parse(String jsonStr, TypeReference<T> valueTypeRef) {
        try {
            if (jsonStr == null) {
                return null;
            }
            return OBJECT_MAPPER.readValue(jsonStr, valueTypeRef);
        } catch (JsonProcessingException e) {
            throw new CrawlerException(e);
        }
    }

}
